/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tchepannou.limbe.gae.service;

import com.tchepannou.limbe.mail.Attachment;
import com.tchepannou.limbe.mail.MailController;
import com.tchepannou.limbe.service.MailService;
import com.tchepannou.limbe.service.OptionService;
import com.tchepannou.limbe.service.impl.AbstractService;
import com.tchepannou.util.StringUtil;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;


/**
 * Default implementation of {@link MailService}.
 * 
 * @author herve
 */
public class GaeMailService
    extends AbstractService
    implements MailService
{
    //-- Static Attribute
    private static final Logger LOG = Logger.getLogger (GaeMailService.class.getName ());
    

    //-- MailService overrides
    @Override
    public void send (MailController controller)
        throws MessagingException, IOException
    {
        if (!controller.hasRecipients ())
        {
            LOG.warning ("Not recipients. No email to send");
            return;
        }

        /* log */

        /* Open the Session */
        Properties properties = new Properties ();
        Session session = Session.getInstance (properties, null);
        OptionService os = findService (OptionService.class);
        MimeMessage mm = createMimeMessage (controller, session, os);
        
//        LOG.info ("");
//        LOG.info (" From:    " + toString(mm.getFrom ()));
//        LOG.info (" ReplyTo: " + toString(mm.getReplyTo ()));
//        LOG.info (" Sender:  " + mm.getSender ());
//        LOG.info (" To:      " + toString (mm.getRecipients (Message.RecipientType.TO)));
//        LOG.info (" CC:      " + toString (mm.getRecipients (Message.RecipientType.CC)));
//        LOG.info (" Bcc:     " + toString (mm.getRecipients (Message.RecipientType.BCC)));
//        LOG.info (" Subject: " + mm.getSubject ());
//        LOG.info ("");
        
        Transport.send (mm);
    }

    //-- Private methods
    private MimeMessage createMimeMessage (MailController controller, Session session, OptionService os)
        throws MessagingException, IOException
    {
        MimeMessage msg = new MimeMessage (session);
        setSender (controller, msg, os);
        setReplyTo (controller, msg);
        setFrom (controller, msg, os);
        addRecipients (controller, msg);
        setSubject (controller, msg);

        Multipart content = new MimeMultipart();
        msg.setContent (content);
        
        /* Text */
        String body = controller.getBody ();
        if (!StringUtil.isEmpty (body))
        {
            MimeBodyPart part = new MimeBodyPart();
            part.setContent (body, controller.getContentType ());
            content.addBodyPart (part);
        }

        /* Attachments */
        List<Attachment> attachments = controller.getAttachments ();
        for (Attachment attachment : attachments)
        {
            MimeBodyPart part = attachment.toBodyPart();
            content.addBodyPart(part);
        }

        return msg;
    }

    private void setFrom (MailController controller, MimeMessage msg, OptionService os)
        throws MessagingException
    {
        InternetAddress from = controller.getFrom ();
        if ( from == null )
        {
            String mailFrom = os.get (OptionService.OPTION_MAIL_FROM, null);;
            if (mailFrom != null)
            {
                from = new InternetAddress(mailFrom);
            }
        }
        if (from == null)
        {
            msg.setFrom (from);
        }
    }
    
    private void setSender (MailController controller, MimeMessage msg, OptionService os)
        throws MessagingException
    {
        String from = os.get (OptionService.OPTION_MAIL_FROM, null);
        if ( !StringUtil.isEmpty (from) )
        {
            msg.setSender (new InternetAddress (from));
        }
    }
    
    private void setReplyTo (MailController controller, MimeMessage msg)
        throws MessagingException
    {
        InternetAddress replyTo = controller.getReplyTo ();
        if (replyTo != null)
        {
            msg.setReplyTo (new InternetAddress[] {replyTo});
        }
    }

    private void addRecipients (MailController controller, MimeMessage msg)
        throws MessagingException
    {
        addRecipients (controller.getTo (), Message.RecipientType.TO, msg);
        addRecipients (controller.getCc (), Message.RecipientType.CC, msg);
        addRecipients (controller.getBcc (), Message.RecipientType.BCC, msg);
    }

    private void addRecipients (List<InternetAddress> recipients, Message.RecipientType type, MimeMessage msg)
        throws MessagingException
    {
        for ( InternetAddress recipient: recipients )
        {
            msg.addRecipient (type, recipient);
        }
    }

    private void setSubject (MailController controller, MimeMessage msg)
        throws MessagingException
    {
        String subject = controller.getSubject ();
        msg.setSubject (!StringUtil.isEmpty (subject)
            ? subject
            : StringUtil.EMPTY);
    }
    
//    private String toString(Address[] address)
//    {
//        StringBuilder sb = new StringBuilder ();
//        if (address != null)
//        {
//            for (Address addr : address)
//            {
//                sb.append(addr.toString ()).append(',');
//            }
//        }
//        return sb.toString ();
//    }
}
